package com.juzishuke.margin.framework;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.Validate;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.util.HashMap;
import java.util.Map;

/**
 * @author : libo@juzishuke.com
 * @Title :
 * @Description :
 * @date : 2024/4/9 17:48
 * @since :1.0
 */
@Slf4j
public class AppContext  implements ApplicationContextAware, InitializingBean {
    
     final static ThreadLocal<Map<String, Object>> threadLocal = new InheritableThreadLocal<>();
    
    private  static ApplicationContext applicationContext;
    @Override
    public void afterPropertiesSet() throws Exception {
    
    }
    public static <T> T getBean(Class<T> clazz) {
        try {
            return getApplicationContext().getBean(clazz);
        } catch (Exception e) {
            return null;
        }
    }
    
    public static <T> T getBean(String name) {
        return (T) getApplicationContext().getBean(name);
    }
    
    public static <T> T getBean(String name, Class<T> clazz) {
        return (T) getApplicationContext().getBean(name, clazz);
    }
    
    public static <T> T getBeanNoEx(String name, Class<T> clazz) {
        try {
            return (T) getApplicationContext().getBean(name, clazz);
        } catch (Exception e) {
            log.warn("No such bean,{}",name);
            return null;
        }
    }
    public static ApplicationContext getApplicationContext() {
        Validate.validState(applicationContext != null, "ApplicationContext属性未注入.");
        return applicationContext;
    }
    @Override
    public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
        AppContext.applicationContext = applicationContext;
    }
    
    public static <T> T getThreadLocal(String key) {
        Map<String, Object> map = threadLocal.get();
        if (map == null) {
            return null;
        }
        Object obj = map.get(key);
        if (obj == null) {
            return null;
        }
        return (T) obj;
    }
    
    /**
     * context 设置线程变量
     *
     * @param key
     * @param value
     */
    public static void setThreadLocal(String key, Object value) {
        Map<String, Object> map = threadLocal.get();
        if (map == null) {
            map = new HashMap<>();
            threadLocal.set(map);
        }
        map.put(key, value);
    }
    public static <T> T removeThreadLocal(String key) {
        Map<String, Object> map = threadLocal.get();
        if (map == null) {
            return null;
        }
        Object obj = map.get(key);
        if (obj == null) {
            return null;
        }
        return (T) map.remove(key);
    }
    public static void delThreadLocal(String key) {
        Map<String, Object> map = threadLocal.get();
        if (MapUtils.isNotEmpty(map)) {
            map.remove(key);
        }
    }
    public void clearThreadLocal(){
        threadLocal.remove();
    }
    
}
